//
// Created by liaohailong on 2025/4/11.
//

#include "HelloLocalFetcher.hpp"


HelloLocalFetcher::HelloLocalFetcher(const std::shared_ptr<HelloCacheManager> &cache,
                                     const std::shared_ptr<HelloHttpRequest> &request,
                                     const std::shared_ptr<HelloRange> &range)
        : HelloDataFetcher(cache, request, range, "HelloLocalFetcherVictor"), cachedRange(nullptr)
{
    logger.i("HelloLocalFetcher::HelloLocalFetcher(%p)", this);
}

HelloLocalFetcher::~HelloLocalFetcher()
{
    logger.i("HelloLocalFetcher::~HelloLocalFetcher(%p)", this);
}

void HelloLocalFetcher::setCachedRange(const std::shared_ptr<HelloRange> &range)
{
    this->cachedRange = range;
}

bool HelloLocalFetcher::run(const std::shared_ptr<HelloHttpRequest> &request)
{
    if (!cachedRange)
    {
        logger.e("local cache file is null? what should i send to the client?");
        return false;
    }
    // 客户端连接句柄
    const int fd = request->getConnFd();

    // 先发送 header 给客户端
    bool success = sendHeader();
    if (!success)
    {
        logger.e("sent HTTP Response header to client was failed");
        return false;
    }

    // 写回客户端：body
    const std::shared_ptr<HelloFile> &file = cachedRange->file;
    // eg:
    // cached [50,100]      [50,400]
    // client [70,200]      [70,200]
    // result [70,100]      [70,200]
    // start offset  70-50=20              70-50=20
    // cached length min(200,100)-70=30    min(400,200)-70=130
    int64_t startOffset = range->start - cachedRange->start;
    int64_t cachedLength = std::min(cachedRange->end, range->end) - range->start + 1;

    success = file->readFileBinary(startOffset, cachedLength,
                                        [&](char *buffer, long size) -> bool {
                                            // 量大，用健壮IO写出
                                            return send(fd, buffer, size, 0) == size;
                                        });
    if (!success)
    {
        logger.e("An error occurred while writing to the client.");
    }

    return success;
}